package org.footballmanager.pandafootball.common.redis;

import org.apache.ibatis.cache.Cache;
import org.footballmanager.pandafootball.common.exception.ExceptionEnum;
import org.footballmanager.pandafootball.common.exception.MyException;
import org.springframework.data.redis.connection.RedisClusterConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;

import java.util.Set;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 使用Redis来做Mybatis的二级缓存
 * 实现Mybatis的Cache接口
 *
 * @author chenjian
 * @since 2017年10月18日下午5:17:22
 */
public class MybatisRedisCache implements Cache {
    private static final String PREFIX = "SYS_CONFIG:";
    private static RedisConnectionFactory redisConnectionFactory;
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
    private String id;
    private JdkSerializationRedisSerializer jdkSerializer = new JdkSerializationRedisSerializer();

    /**
     * 构造函数
     *
     * @param id
     */
    public MybatisRedisCache(final String id) {
        if (id == null) {
            throw new MyException(ExceptionEnum.NEEDIDEXCEPTION, new Exception());
        }
        this.id = id;
    }

    /**
     * 获取redis工厂对象
     *
     * @param redisConnectionFactory 参数
     */
    public static void setRedisConnectionFactory(RedisConnectionFactory redisConnectionFactory) {
        MybatisRedisCache.redisConnectionFactory = redisConnectionFactory;
    }

    /**
     * 获取主键
     *
     * @return
     */
    @Override
    public String getId() {
        return this.id;
    }

    /**
     * 设置对象
     *
     * @param key   参数
     * @param value 参数
     */
    @Override
    public void putObject(Object key, Object value) {
        RedisClusterConnection conn = redisConnectionFactory
                .getClusterConnection();
        if (key == null)
            return;
        String strKey = PREFIX + key.toString();
        conn.set(strKey.getBytes(), jdkSerializer.serialize(value));
        conn.close();
    }

    /**
     * 获取对象
     *
     * @param key 参数
     * @return 返回值
     */
    @Override
    public Object getObject(Object key) {
        if (key != null) {
            String strKey = PREFIX + key.toString();
            RedisClusterConnection conn = redisConnectionFactory
                    .getClusterConnection();
            byte[] bs = conn.get(strKey.getBytes());
            conn.close();
            return jdkSerializer.deserialize(bs);
        }
        return null;
    }

    /**
     * 删除对象
     *
     * @param key 参数
     * @return 返回值
     */
    @Override
    public Object removeObject(Object key) {
        if (key != null) {
            RedisClusterConnection conn = redisConnectionFactory
                    .getClusterConnection();
            conn.del(key.toString().getBytes());
            conn.close();
        }
        return null;
    }

    /**
     * 清空数据
     */
    @Override
    public void clear() {
        // 关键代码，data更新时清理缓存
        RedisClusterConnection conn = redisConnectionFactory
                .getClusterConnection();
        Set<byte[]> keys = conn.keys((PREFIX + "*").getBytes());
        for (byte[] bs : keys) {
            conn.del(bs);
        }
        conn.close();
    }

    /**
     * 获取大小
     *
     * @return 返回值
     */
    @Override
    public int getSize() {
        return 0;
    }

    /**
     * 获取读写锁
     *
     * @return
     */
    @Override
    public ReadWriteLock getReadWriteLock() {
        return this.readWriteLock;
    }
}
